// 定义字符串
// 类型不写也会做自动类型推断
let str: string = "hello";
str = "world";
let str2: string;
str2 = "haha";

// 定义数字类型
let num1: number = 10;
num1 = 11;

// 定义布尔值类型
let done: boolean = true;
done = false;

// 定义undefined
// undefined类型只有undefined一个值，定义好了就不能更改了
let udf: undefined = undefined;

// 定义null
let nl: null = null;

// 联合类型
let a: number | string | boolean = 5;
a = "5";
a = true;
// const b: string | null = localStorage.getItem("token");
// if (b) {
//   b.split(",");
// }

// 任何类型 any
let abc: any = 4;
abc = [1, 2, 3];

// 数组类型
let arr1: number[] = [1, 2, 3, 4];
let arr2: Array<string> = ["a", "b", "c"];
let arr3: (number | string | boolean)[] = [1, "2", 3, true];
let arr4: Array<number | string | boolean> = [1, "2", 3, true];
let arr5: Array<number | number[]> = [1, 2, [3, 4, 5]];
let arr6: Array<any> = [1, 2, [3, 4, 5]];
let arr7: any = [1, 2, [3, 4, 5]];

// 元组类型Tuple
// 元组类型是特殊的数组类型, 不仅规定了数组的长度，还规定了里面的每一项的数据类型
let arr8: [number, string] = [1, "hello"];
// arr8 = ["1", "hello"];
// arr8.splice(2);
// arr8[2];

// 对象类型
// 对象类型定义需要使用接口 interface
interface ObjType {
  name: string;
  age: number;
  // 问好表示可选参数
  sex?: number;
  // 索引签名
  [propname: string]: any;
}

let obj1: ObjType = {
  name: "zhangsan",
  age: 20,
  abc: function () {},
};

obj1.sex = 1;

interface ItemType {
  id: number;
  name: string;
}
let arr10: ItemType[] = [
  {
    id: 1,
    name: "zhangsan",
  },
  {
    id: 2,
    name: "lisi",
  },
];

interface Obj2Type {
  id: number;
  name: string;
  children?: Obj2Type[];
}
let obj2: Obj2Type = {
  id: 1,
  name: "zhangsan",
  children: [
    {
      id: 2,
      name: "zhangsi",
      children: [
        {
          id: 4,
          name: "zhangliu",
        },
      ],
    },
    {
      id: 3,
      name: "zhangwu",
    },
  ],
};

// 枚举类型 Enum
// 类似于对象，可以从key找到value，也可以从value找到key
enum Color {
  Red = 5,
  Green = 10,
  Blue = 15,
}
let g: Color = Color.Green;
// console.log(g);
let colorname: string = Color[15];
// console.log(colorname);

// 函数类型
function add(x: number, y: string): string {
  return x + y;
}
add(3, "4");

const add2: (x: number, y: number) => number = (
  x: number,
  y: number
): number => {
  return x + y;
};
add2(5, 6);

function fn1(a: number, b?: number): number {
  if (b) {
    return a + b;
  } else {
    return a;
  }
}
fn1(3);

// void表示没有返回值，专门给函数用的
function fn2(): void {
  console.log(123);
}

// never表示从不，用于函数，函数死循环或者报错
function fn3(): never {
  throw new Error("xxx");
}
function fn4(): never {
  while (true) {}
}

// 泛型
function fn5<T>(x: T, y: T) {
  return 123;
}
fn5<string>("3", "4");

// const count = ref<number>(5);

// 类
interface ParamsType {
  names: string;
}
class Animal {
  constructor(obj: ParamsType) {
    this.names = obj.names;
  }
  names: string = "dog";
  sayName(): string {
    return this.names;
  }
}

class Cat extends Animal {
  // constructor是一个特殊的函数，在这个构造函数被实例化的时候调用
  constructor(obj: ParamsType) {
    // super函数是用来触发父类的constructor
    super(obj);
  }
}

const cat = new Cat({
  names: "cat",
});

console.log(cat.names);
